#include "svm_classifier.h"

/*
	分类器创建
	-创建数据结构
	-赋值
	--权值随机数
	--梯度置0
	--常数赋值
*/
svm_classifier* svm_classifier_Create(float c)
{
	int i = 0;
	svm_classifier *ptr = NULL;
	if ((ptr = (svm_classifier*)malloc(sizeof(svm_classifier))) == NULL) {
		printf("svm classifier create failed!\n");
		return NULL;
	}
	srand((unsigned)time(NULL));
	ptr->weight_length = 4125;//长度定义 
	ptr->Constant_B = 1;
	ptr->Constant_C = c;//常数赋值
	for (i = 0; i < 4125; i++) {
		ptr->weight[i] = ((float)(rand() % 10)) / 10.0;//权值随机数
	}
	return ptr;
}

SMO_Pram * SMO_classisifier_Create(input_data *DList,float c)
{
	SMO_Pram *ptr;
	long int i;
	if ((ptr = (SMO_Pram*)malloc(sizeof(SMO_Pram))) == NULL) {
		printf("SMO struct create failed!");
		return NULL;
	}
	ptr->length = DList->length;
	if (((ptr->alpha = (double*)malloc(ptr->length * sizeof(double))) == NULL)
		|| ((ptr->E = (double*)malloc(ptr->length * sizeof(double))) == NULL)
		|| ((ptr->b = (double*)malloc(ptr->length * sizeof(double))) == NULL)
		) {
		printf("SMO dataArea create failed!");
		free(ptr);
		return NULL;
	}
	for (i = 0; i < ptr->length; i++) {
		ptr->alpha[i] = 0;
		ptr->E[i] = 0;
		ptr->b[i] = 0;
	}
	ptr->c = c;
	return ptr;
}

double Dual_Loss_Function(svm_classifier * classifier, input_data * Dlist)
{
	double output;
	double temp;
	unsigned long int i, j;
	element* pNode;
	//合法性检验
	if (classifier == NULL || Dlist == NULL || Dlist->length == 0) {
		printf("Empty classifier or datalist");
		return -1;
	}
	pNode = Dlist->head;
	output = temp = 0.0;
	while (pNode) {
		temp = 0.0;
		for (i = 0; i < classifier->weight_length; i++) {
			for (j = 0; j < classifier->weight_length; j++) {
				
			}
		}
	}
	return 0.0;
}

//判断全局KKT条件是否满足
int SMO_CheckKKT(SMO_Pram * smo, input_data * Dlist, double eps)
{

	return 0;
}

//寻找外层循环中“违背KKT条件”的alpha索引
long int SMO_OuterIndex(SMO_Pram * smo, input_data * Dlist, double eps, long int startindex = 0)
{
	long int index = 0;
	int flag = 0;
	element *pNode;
	if (smo == NULL || Dlist == NULL || Dlist->length == 0) {
		printf("Classifier or data is not ready");
		exit(1);
	}
	if ((startindex >= Dlist->length) || (startindex<0)) {
		printf("Illegal index!");
		exit(1);
	}
	pNode = Dlist->head;
	while (index != startindex) {
		index++;
		pNode = pNode->next;
	}//定位至起点
	//判断KKT
	while (pNode) {
		flag = 0;
		if (fabs(smo->alpha[index]) < eps) {
			if ((fabs(pNode->result*SMO_gFunction(smo, Dlist, index) - 1) >0) || (fabs(pNode->result*SMO_gFunction(smo, Dlist, index) - 1) <=eps)) {
				flag = 1;
			}
		}
		else if ((smo->alpha[index] > 0) && (smo->alpha[index] < smo->c)) {
			if (fabs(pNode->result*SMO_gFunction(smo, Dlist, index) - 1) <= eps) {
				flag = 1;
			}
		}
		else {
			if (((fabs(pNode->result*SMO_gFunction(smo, Dlist, index)) - 1) < 0) || ((fabs(pNode->result*SMO_gFunction(smo, Dlist, index)) - 1) <= eps)) {
				flag = 1;
			}
		}
		if (flag == 1) {
			break;
		}
	}
	if (flag == 1) {
		return index;
	}
	else {
		return -1;
	}
}

//寻找内循环索引值,寻找max|E[outerindex]-E[i]|
long int SMO_InnerIndex(SMO_Pram * smo, long int outerindex)
{
	long int i, index;
	double min_value=0;
	double temp;
	for (i = 0; i < smo->length; i++) {
		if (i == outerindex) {
			temp = 0;
			continue;
		}
		temp = fabs((smo->E[outerindex] - smo->E[i]));
		if (temp > min_value) {
			index = i;
			min_value = temp;
		}
		temp = 0;
	}
	return index;
}

//计算G函数
double SMO_gFunction(SMO_Pram * smo, input_data * Dlist, long int index)
{
	double output=0.0;
	element *pNode;
	long int i;
	if (smo == NULL || Dlist == NULL || Dlist->length == 0) {
		printf("Classifier or data is not ready");
		exit(1);
	}
	pNode = Dlist->head;
	for (i = 0; i < smo->length&&pNode != NULL; i++) {
		output += smo->alpha[i%smo->length] * pNode->result*SMO_DotProduct(Dlist, i, index);
		pNode = pNode->next;
	}
	return output + smo->b[index];
}

//计算点积
double SMO_DotProduct(input_data * Dlist, long int index1, long int index2)
{
	long int i=0;
	double output = 0.0;
	element *pNodeIndex1, *pNodeIndex2, *pNode;
	pNodeIndex1 = pNodeIndex2 = NULL;
	pNode = Dlist->head;
	while (pNodeIndex1&&pNodeIndex2) {
		if (i == index1) {
			pNodeIndex1 = pNode;
		}
		if (i == index2) {
			pNodeIndex2 = pNode;
		}
		pNode = pNode->next;
		i++;
	}
	for (i = 0; i < pNodeIndex1->vec_length; i++) {
		output += pNodeIndex1->data_vec[i] * pNodeIndex2->data_vec[i];
	}
	return output;
}
